package com.zhangmeng.tools.dto;

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//


import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javax.naming.NoPermissionException;
import net.imyeyu.timifx.TimiFX;
import net.imyeyu.timifx.component.ContextMenu;
import net.imyeyu.timifx.component.XTreeView;
import net.imyeyu.timifx.component.alert.AlertConfirm;
import net.imyeyu.timifx.component.alert.AlertTextField;
import net.imyeyu.timifx.component.alert.AlertTips;
import net.imyeyu.timifx.component.alert.AlertButton.Action;
import net.imyeyu.timifx.icon.TimiFXIcon;
import net.imyeyu.timifx.service.RunAsync;
import net.imyeyu.timijava.IO;
import net.imyeyu.timijava.Lang;
import net.imyeyu.timijava.TimiJava;
import net.imyeyu.timijava.bean.CallbackReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileTreeView extends XTreeView<File> implements TimiFX {
    private static final Logger log = LoggerFactory.getLogger(net.imyeyu.timifx.component.FileTreeView.class);
    protected final BooleanBinding findingItem;
    protected final BooleanProperty showHide = new SimpleBooleanProperty(false);
    protected final ObservableList<File> selectDeque = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    protected final List<CallbackReturn<File, Boolean>> itemFilters = new ArrayList();

    public FileTreeView(File root) {
        this.findingItem = Bindings.isNotEmpty(this.selectDeque);
        this.disableProperty().bind(this.findingItem);
        this.setCellFactory((cell) -> {
            return new TreeCell<File>() {
                final Label loading = new Label(Lang.text("public.loading"));
                final Text iconFile = TimiFXIcon.fromName("FILE");
                final Text iconDirectory = TimiFXIcon.fromName("FOLDER");

                {
                    this.iconFile.fillProperty().bind(Bindings.when(FileTreeView.this.focusedProperty().and(this.selectedProperty())).then(TimiFX.GRAY_WHITE).otherwise(TimiFX.GRAY));
                    this.iconDirectory.fillProperty().bind(Bindings.when(FileTreeView.this.focusedProperty().and(this.selectedProperty())).then(TimiFX.GRAY_WHITE).otherwise(TimiFX.GRAY));
                }

                protected void updateItem(File file, boolean empty) {
                    super.updateItem(file, empty);
                    if (empty) {
                        this.setText("");
                        this.setGraphic((Node)null);
                    } else if (file == null) {
                        this.setGraphic(this.loading);
                    } else {
                        if (TimiJava.isEmpty(file.getName())) {
                            this.setText(file.toString());
                        } else {
                            this.setText(file.getName());
                        }
                        this.setFont(new Font(15));
                        this.setGraphic(file.isFile() ? this.iconFile : this.iconDirectory);
                    }

                }
            };
        });
        MenuItem menuMkdir = new MenuItem(Lang.text("timifx.file.mkdir"), TimiFXIcon.fromName("FOLDER_ADD"));
        MenuItem menuRename = new MenuItem(Lang.text("public.rename"));
        MenuItem menuRefresh = new MenuItem(Lang.text("public.refresh"), TimiFXIcon.fromName("REFRESH"));
        MenuItem menuDestroy = new MenuItem(Lang.text("public.delete"), TimiFXIcon.fromName("FAIL", RED));
        this.setContextMenu(new ContextMenu(new MenuItem[]{menuMkdir, menuRename, menuRefresh, TimiFX.sep(), menuDestroy}));
        menuMkdir.disableProperty().bind(menuRefresh.disableProperty());
        menuMkdir.setOnAction((e) -> {
            this.mkdir((TreeItem)this.getSelectionModel().getSelectedItem());
        });
        menuRename.disableProperty().bind(TimiFX.onlyOnceInList(this.getSelectionModel().getSelectedItems()).not());
        menuRename.setOnAction((e) -> {
            this.rename((TreeItem)this.getSelectionModel().getSelectedItem());
        });
        menuRefresh.disableProperty().bind(Bindings.createBooleanBinding(() -> {
            List<TreeItem<File>> items = this.getSelectionModel().getSelectedItems();
            return items == null || items.size() != 1 || ((File)((TreeItem)items.get(0)).getValue()).isFile();
        }, new Observable[]{this.getSelectionModel().selectedItemProperty()}));
        menuRefresh.setOnAction((e) -> {
            this.refreshItem((TreeItem)this.getSelectionModel().getSelectedItem());
        });

        List<File> roots = new ArrayList<>();
        if (root != null){
            roots.add(root);
        }

        menuDestroy.disableProperty().bind(Bindings.createBooleanBinding(() -> {
            ObservableList<TreeItem<File>> items = this.getSelectionModel().getSelectedItems();
            if (items.isEmpty()) {
                return true;
            } else {
                for(int i = 0; i < items.size(); ++i) {
                    if (roots.contains(((TreeItem)items.get(i)).getValue())) {
                        return true;
                    }
                }

                return false;
            }
        }, new Observable[]{this.getSelectionModel().getSelectedItems()}));
        menuDestroy.setOnAction((e) -> {
            this.destroy(this.getSelectionModel().getSelectedItems());
        });
        this.addEventFilter(KeyEvent.KEY_RELEASED, (e) -> {
            boolean control = e.isControlDown();
            boolean shift = e.isShiftDown();
            boolean alt = e.isAltDown();
            KeyCode code = e.getCode();
            if (!control && !shift && !alt) {
                switch(code) {
                    case F2:
                        menuRename.fire();
                        break;
                    case F5:
                        menuRefresh.fire();
                        break;
                    case DELETE:
                        menuDestroy.fire();
                }
            }

            if (control && shift && !alt && code == KeyCode.N) {
                menuMkdir.fire();
            }

        });
        CallbackReturn<File, Boolean> filterHidden = (file) -> {
            return !file.isHidden();
        };
        this.itemFilters.add(filterHidden);
        this.showHide.addListener((obs, o, n) -> {
            if (this.isShowHide()) {
                this.itemFilters.remove(filterHidden);
            } else {
                this.itemFilters.add(filterHidden);
            }

        });

        for(int i = 0; i < roots.size(); ++i) {
            this.getRoots().add(new FileItem((File)roots.get(i)));
        }

    }

    public void mkdir(TreeItem<File> base) {
        if (base != null) {
            AlertTextField alert = new AlertTextField(Lang.text("timifx.file.mkdir"));
            alert.setTips(Lang.text("public.name"));
            alert.setOnActionEvent((action) -> {
                if (action == Action.CONFIRM) {
                    try {
                        String var10000 = IO.fitPath(((File)base.getValue()).getAbsolutePath());
                        IO.dir(var10000 + alert.getText());
                        this.refreshItem((TreeItem)this.getSelectionModel().getSelectedItem());
                    } catch (NoPermissionException var5) {
                        var5.printStackTrace();
                    }
                }

                return true;
            });
            alert.autoSize().showRelativeCenter(this.getScene().getWindow());
        }
    }

    public void rename(TreeItem<File> file) {
        if (file != null) {
            AlertTextField alert = new AlertTextField(Lang.text("timifx.file.rename"));
            alert.setTips(Lang.text("public.name"));
            alert.setOnActionEvent((action) -> {
                if (action == Action.CONFIRM) {
                    IO.rename((File)((TreeItem)this.getSelectionModel().getSelectedItem()).getValue(), alert.getText());
                    this.refreshItem(((TreeItem)this.getSelectionModel().getSelectedItem()).getParent());
                }

                return true;
            });
            alert.autoSize().showRelativeCenter(this.getScene().getWindow());
        }
    }

    public void destroy(final List<TreeItem<File>> files) {
        if (!TimiJava.isEmpty(files)) {
            (new AlertConfirm(Lang.text("timifx.file.destroy")) {
                protected void onConfirm() {
                    (new RunAsync<TreeItem<File>>() {
                        protected TreeItem<File> call() {
                            List<File> items = files.stream().map(TreeItem::getValue).toList();

                            int l;
                            for(l = 0; l < items.size(); ++l) {
                                IO.destroy((File)items.get(l));
                            }

                            l = 2147483647;
                            TreeItem<File> item = null;

                            for(int i = 0; i < items.size(); ++i) {
                                int j = FileTreeView.this.getTreeItemLevel((TreeItem)files.get(i));
                                if (j < l) {
                                    l = j;
                                    item = (TreeItem)files.get(i);
                                    if (item.getParent() != null) {
                                        item = item.getParent();
                                    }
                                }
                            }

                            return item;
                        }

                        protected void onFinish(TreeItem<File> item) {
                            if (item != null) {
                                FileTreeView.this.refreshItem(item);
                            }

                        }

                        protected void onException(Throwable e) {
                            log.error("destroy fail", e);
                            AlertTips.error(getScene().getWindow(), Lang.text("timifx.file.destroy_fail"));
                        }
                    }).start();
                }
            }).autoSize().showRelativeCenter(this.getScene().getWindow());
        }
    }

    public void refreshItem(TreeItem<File> treeItem) {
        if (treeItem instanceof net.imyeyu.timifx.component.FileTreeView.FileItem) {
            FileTreeView.FileItem fileItem = (FileTreeView.FileItem)treeItem;
            fileItem.getChildren().clear();
            fileItem.getChildren().add(new FileTreeView.FileItem());
            fileItem.asyncLoadChildren();
        }

    }

    public void refreshItem(FileTreeView.FileItem fileItem) {
        fileItem.getChildren().clear();
        fileItem.getChildren().add(new FileTreeView.FileItem());
        fileItem.asyncLoadChildren();
    }

    public void selectItem(String path) {
        if (TimiJava.isEmpty(path)) {
            path = "./";
        }

        this.selectItem(new File(path));
    }

    public void selectItem(File file) {
        File parent = file.getAbsoluteFile();
        if (!parent.exists()) {
            parent = (new File("./")).getAbsoluteFile();
        }

        do {
            this.selectDeque.add(0, parent);
        } while((parent = parent.getParentFile()) != null);

        if (TimiJava.isNotEmpty(this.selectDeque)) {
            ObservableList<TreeItem<File>> roots = this.getRoots();

            for(int i = 0; i < roots.size(); ++i) {
                ((TreeItem)roots.get(i)).setExpanded(false);
                if (((File)((TreeItem)roots.get(i)).getValue()).equals(this.selectDeque.get(0))) {
                    this.selectDeque.remove(0);
                    ((TreeItem)roots.get(i)).setExpanded(true);
                    if (TimiJava.isEmpty(this.selectDeque)) {
                        break;
                    }
                }
            }
        }

    }

    /** @deprecated */
    @Deprecated
    public void setItemFactory(CallbackReturn<File, Boolean> itemFactory) {
        this.itemFilters.clear();
        this.itemFilters.add(itemFactory);
    }

    public void addItemFilter(CallbackReturn<File, Boolean> itemFilter) {
        this.itemFilters.add(itemFilter);
    }

    public void removeItemFilter(CallbackReturn<File, Boolean> itemFilter) {
        this.itemFilters.remove(itemFilter);
    }

    public void setShowHide(boolean showHide) {
        this.showHide.set(showHide);
    }

    public boolean isShowHide() {
        return this.showHide.get();
    }

    public BooleanProperty showHideProperty() {
        return this.showHide;
    }

    public BooleanBinding findingItemProperty() {
        return this.findingItem;
    }

    public final class FileItem extends TreeItem<File> {
        FileItem() {
            this((File)null);
        }

        FileItem(File file) {
            super(file);
            if (file != null && file.isDirectory()) {
                this.getChildren().add(FileTreeView.this.new FileItem((File)null));
            }

            this.expandedProperty().addListener((obs, o, isExpanded) -> {
                if (isExpanded) {
                    FileTreeView.this.getSelectionModel().clearSelection();
                    FileTreeView.this.getSelectionModel().select(this);
                    this.asyncLoadChildren();
                } else {
                    this.getChildren().add(FileTreeView.this.new FileItem());
                }

            });
        }

        void asyncLoadChildren() {
            RunAsync.runback(() -> {
                List<FileTreeView.FileItem> fileItems = new ArrayList();
                File[] files = ((File)this.getValue()).listFiles();
                if (files != null) {
                    List<File> fileList = Arrays.stream(files).sorted(TimiJava.COMPARATOR_FILE_NAME).toList();

                    label26:
                    for(int i = 0; i < fileList.size(); ++i) {
                        for(int j = 0; j < FileTreeView.this.itemFilters.size(); ++j) {
                            if (!(Boolean)((CallbackReturn) FileTreeView.this.itemFilters.get(j)).handler((File)fileList.get(i))) {
                                continue label26;
                            }
                        }

                        fileItems.add(FileTreeView.this.new FileItem((File)fileList.get(i)));
                    }
                }

                return fileItems;
            }, (items) -> {
                this.getChildren().setAll(items);
                if (TimiJava.isNotEmpty(FileTreeView.this.selectDeque)) {
                    File file = (File) FileTreeView.this.selectDeque.remove(0);

                    for(int i = 0; i < items.size(); ++i) {
                        if (((File)((FileTreeView.FileItem)items.get(i)).getValue()).equals(file)) {
                            if (((File)((FileTreeView.FileItem)items.get(i)).getValue()).isDirectory()) {
                                ((FileTreeView.FileItem)items.get(i)).setExpanded(true);
                            }
                            break;
                        }
                    }

                    if (TimiJava.isEmpty(FileTreeView.this.selectDeque)) {
                        Platform.runLater(() -> {
                            FileTreeView.this.scrollTo(FileTreeView.this.getSelectionModel().getSelectedIndex() - 5);
                        });
                    }
                }

            });
        }
    }
}

